define(function(require, exports, module) {

  // var Backbone = require('backbone');
  var $ = require('jquery');
  var _ = require('lodash');
  // var jsonview = require('jsonview');
  var tmpl = require('text!../tmpl.html');

  var littleCanvas = require('hy5b/frontend/canvas/littleCanvas')
  var d3 = require('d3')

  var flow = require('js/link/flow')

  function main() {
    var $app = $('<div id="app">');
    $('#main').html($app);

    $app.append(tmpl);

    var lc = new littleCanvas(document.getElementById('arcline'))

    var colors = [
      ['rgba(229, 58, 32, 0.5)', 'rgba(229, 58, 32, 1)'],
      ['rgba(51, 96, 208, 0.5)', 'rgba(51, 96, 208, 1)'],
      ['rgba(112, 86, 151, 0.5)', 'rgba(112, 86, 151, 1)'],
    ]

    var points = [
      [20,20],
      [150,20],
      [150,200],
      [200,200]
    ]

    function draw(flowPoints) {
      lc.clear()

      lc.draw(function(ctx) {
        ctx.moveTo(points[0][0], points[0][1]);
        ctx.lineTo(points[1][0], points[1][1])
        ctx.lineTo(points[2][0], points[2][1])
  
        ctx.strokeStyle = colors[0][0]
        ctx.stroke();
      })
  
      lc.draw(function(ctx) {
        ctx.moveTo(points[0][0], points[0][1]);           // 创建开始点
        ctx.arcTo(points[1][0], points[1][1],points[2][0], points[2][1],50); // 创建弧
        // ctx.lineTo(points[2][0], points[2][1]);         // 创建垂直线
        ctx.strokeStyle = colors[0][1]
        ctx.stroke();                // 进行绘制
      })
  
  
      lc.draw(function(ctx) {
        ctx.moveTo(points[0][0], points[0][1]);
        ctx.lineTo(points[1][0], points[1][1])
        ctx.lineTo(points[3][0], points[3][1])
  
        ctx.strokeStyle = colors[1][0]
        ctx.stroke();
      })
  
      lc.draw(function(ctx) {
        ctx.moveTo(points[0][0], points[0][1]);           // 创建开始点
        ctx.arcTo(points[1][0], points[1][1],points[3][0], points[3][1],50); // 创建弧
        // ctx.lineTo(points[2][0], points[2][1]);         // 创建垂直线
        ctx.strokeStyle = colors[1][1]
        ctx.stroke();                // 进行绘制
      })
  
      lc.draw(function(ctx) {
        ctx.moveTo(points[0][0], points[0][1]);           // 创建开始点
        ctx.arcTo(points[1][0], points[1][1],points[3][0], points[3][1],80); // 创建弧
        // ctx.lineTo(points[2][0], points[2][1]);         // 创建垂直线
        ctx.strokeStyle = colors[2][1]
        ctx.stroke();                // 进行绘制
      })

      arcHelper(50, colors[1][0])
      arcHelper(80, colors[2][0])

      _.each(flowPoints, point => {
        lc.draw(function(ctx) {
          ctx.fillStyle = 'red'
          ctx.arc(point[0], point[1], 3, 0, 2 * Math.PI, false)
          ctx.fill();
        })
      })
    }
    
    function arcHelper(radius, color) {
      // console.time('特殊情况 - ' + radius);
      var a = Math.atan(50/180)
      var len = radius / (50 / 180 + 1 / Math.cos(a))
      // console.timeEnd('特殊情况 - ' + radius);
      // console.log(radius, len)
      var A = [150 - len, 20]
      var p0 = [150 + len * Math.sin(a), 20 + len * Math.cos(a)]
      var p1 = [A[0], A[1] + radius]

      lc.draw(function(ctx) {
        ctx.moveTo(p0[0], p0[1])
        ctx.lineTo(p1[0], p1[1])
        ctx.lineTo(A[0], A[1])
        ctx.strokeStyle = color
        ctx.stroke();
      })
    }
    
    var A = points[0]
    var O = points[1]
    var B = points[3]
    console.time('vector')
    var vecOA = [A[0] - O[0], A[1] - O[1]]
    var vecOB = [B[0] - O[0], B[1] - O[1]]

    var dotOAOB = vecOA[0] * vecOB[0] + vecOA[1] * vecOB[1]
    var lenOA = Math.sqrt(vecOA[0] * vecOA[0] + vecOA[1] * vecOA[1])
    var lenOB = Math.sqrt(vecOB[0] * vecOB[0] + vecOB[1] * vecOB[1])

    var degAOBcos = dotOAOB / (lenOA * lenOB)
    var degAOB = Math.acos(degAOBcos)

    var radius = 50

    var cutLen = radius / Math.tan(degAOB / 2)
    console.timeEnd('vector')
    console.log(radius, cutLen)

    var vecOAUnit = [vecOA[0] / lenOA, vecOA[1] / lenOA]
    var vecOBUnit = [vecOB[0] / lenOB, vecOB[1] / lenOB]

    var A0 = [O[0] + cutLen * vecOAUnit[0], O[1] + cutLen * vecOAUnit[1]]
    var B0 = [O[0] + cutLen * vecOBUnit[0], O[1] + cutLen * vecOBUnit[1]]

    var C = [
      ((vecOA[0] * A0[0] + vecOA[1] * A0[1]) * vecOB[1] - (vecOB[0] * B0[0] + vecOB[1] * B0[1]) * vecOA[1]) / (vecOA[0] * vecOB[1] - vecOB[0] * vecOA[1]),
      ((vecOA[0] * A0[0] + vecOA[1] * A0[1]) * vecOB[0] - (vecOB[0] * B0[0] + vecOB[1] * B0[1]) * vecOA[0]) / (vecOA[1] * vecOB[0] - vecOB[1] * vecOA[0])
    ]

    var svg = d3.select('#arclineSvg')
    svg
      .append('path')
      .attr('id', 'path1')
      .attr('stroke', colors[1][1])
      .attr('fill', 'none')
      .attr('d', `M 20 20 \
        L ${A0[0]} ${A0[1]} \
        A ${radius} ${radius} 0 0 1 ${B0[0]} ${B0[1]} \
        L 200 200`)
    svg
      .append('path')
      .attr('stroke', colors[1][0])
      .attr('fill', 'none')
      .attr('d', `M ${A0[0]} ${A0[1]} \
        L ${C[0]} ${C[1]} \
        L ${B0[0]} ${B0[1]}`)
    svg
      .append('circle')
      .attr('r', '3')
      .append('animateMotion')
      .attr('dur', '6s')
      .attr('repeatCount', 'indefinite')
      .append('mpath')
      .attr('xlink:href', '#path1')

    var path1Elem = document.getElementById('path1')
    var path1Len = path1Elem.getTotalLength()
    var p = path1Elem.getPointAtLength(path1Len * 0.4)

    // console.log(path1Elem, path1Len, p)

    svg
      .append('circle')
      .attr('r', '3')
      .attr('fill', 'red')
      .attr('cx', p.x)
      .attr('cy', p.y)


    var offlinePath = document.createElementNS('http://www.w3.org/2000/svg', 'path')
    offlinePath.setAttribute('d', `M ${points[0][0]} ${points[0][1]} \
      L ${A0[0]} ${A0[1]} \
      A ${radius} ${radius} 0 0 1 ${B0[0]} ${B0[1]} \
      L ${points[3][0]} ${points[3][1]}`)
    
    var offlinePathLen = offlinePath.getTotalLength()
    var point = offlinePath.getPointAtLength(offlinePathLen * 0.4)


    var flowAnimate = flow.animationPlus({
      points: [points[0], points[1], points[3]],
      type: 'brokenArc',
      radius: 50
    }, 0.5)

    function step() {
      requestAnimationFrame(step);
      var flowPoints = flowAnimate.get()
      draw(flowPoints)
    }

    requestAnimationFrame(step);
  }

  return main;
})
